#include <my_head.h>

// 程序初始化的函数
sqlite3 *proc_init(){
    // 打开数据库文件
    sqlite3 *my_db = NULL;
    int ret = 0;
    // 打开数据库文件
    if(SQLITE_OK != (ret = sqlite3_open("xja.db", &my_db))){
        printf("sqlite3_open error : [%d] [%s]\n", ret, sqlite3_errmsg(my_db));
        exit(EXIT_FAILURE);
    }
    printf("数据库文件打开成功..\n");
    // 创建数据表
    // 终端上执行sql语句时 结尾需要加分号，代码中使用sql时无需加结尾的分号
    // 注意：表只能创建一次 否则执行建表语句时报错：表已存在
    // 解决方式1：表已存在的错误对应的是 1 号错误码 我们可以根据错误码 忽略1号错误
    // 解决方式2：使用 IF NOT EXISTS 关键  表示如果不存在就新建 存在就直接使用 而不报错
    char sqlbuff[256] = "CREATE TABLE IF NOT EXISTS student(id INT PRIMARY KEY, name CHAR, score INT)";
    char *errmsg = NULL;
    if(SQLITE_OK != (ret = sqlite3_exec(my_db, sqlbuff, NULL, NULL, &errmsg))){
        printf("sqlite3_exec error : [%d] [%s]\n", ret, errmsg);
        exit(EXIT_FAILURE);
    }
    sqlite3_free(errmsg); // 防止内存泄露 释放空间
    printf("创建数据表成功..\n");
    return my_db;
}

// 打印菜单的函数
void print_menu(){
	printf("--------------------------------------\n");
	printf("| 1.添加 2.修改 3.删除 4.查找 5.退出 |\n");
	printf("--------------------------------------\n");
	printf("请输入你的选择:");
}

// 添加学员信息的函数
int insert_student(sqlite3 *my_db){
    printf("请输入新学员的信息(学号 姓名 成绩):");
    int input_id = 0;
    char input_name[32] = {0};
    int input_score = 0;
    scanf("%d%s%d", &input_id, input_name, &input_score);
    // 组装sql语句
    char sqlbuff[256] = {0};
    sprintf(sqlbuff, "INSERT INTO student VALUES(%d, '%s', %d)",\
                input_id, input_name, input_score);
    // 注意：数据库代码遇到执行报错时 第一件事儿 先把要执行的sql语句打印出来 进行分析
    // printf("sqlbuff = [%s]\n", sqlbuff); //debug
    // 执行sql语句
    int ret = 0;
    if(SQLITE_OK != (ret = sqlite3_exec(my_db, sqlbuff, NULL, NULL, NULL))){
        printf("sqlite3_exec error : [%d] [%s]\n", ret, sqlite3_errmsg(my_db));
        exit(EXIT_FAILURE);
    }
    printf("\n\n学员信息添加成功\n\n");
    return 0;
}

// 修改学员信息的函数（根据学号修改名字和成绩）
int modify_student(sqlite3 *my_db){
    printf("请输入要修改的学员的学号:");
    int input_id = 0;
    scanf("%d", &input_id);
    printf("请输入新的姓名和成绩:");
    char input_name[32] = {0};
    int input_score = 0;
    scanf("%s%d", input_name, &input_score);
    // 组装sql语句
    char sqlbuff[256] = {0};
    sprintf(sqlbuff, "UPDATE student SET name='%s',score=%d WHERE id=%d",\
                    input_name, input_score, input_id);
    // 执行sql语句
    int ret = 0;
    if(SQLITE_OK != (ret = sqlite3_exec(my_db, sqlbuff, NULL, NULL, NULL))){
        printf("sqlite3_exec error : [%d] [%s]\n", ret, sqlite3_errmsg(my_db));
        exit(EXIT_FAILURE);
    }
    printf("\n\n学员信息修改成功\n\n");
    return 0;
}

// 删除学员信息的函数（根据名字删除）
int delete_student(sqlite3 *my_db){
    printf("请输入要删除的学员的姓名:");
    char input_name[32] = {0};
    scanf("%s", input_name);
    // 组装sql语句
    char sqlbuff[256] = {0};
    sprintf(sqlbuff, "DELETE FROM student WHERE name='%s'", input_name);
    // 执行sql语句
    int ret = 0;
    if(SQLITE_OK != (ret = sqlite3_exec(my_db, sqlbuff, NULL, NULL, NULL))){
        printf("sqlite3_exec error : [%d] [%s]\n", ret, sqlite3_errmsg(my_db));
        exit(EXIT_FAILURE);
    }
    printf("\n\n学员信息删除成功\n\n");
    return 0;
}

int flag = 0; // 打印表头的标志位  0需要打印 1不需要打印
// 回调函数
int callback(void* arg, int ncolumn, char **f_value, char **f_name){
    // 先打印字段名
    int i = 0;
    if(0 == flag){
        for(i = 0; i < ncolumn; i++){
            printf("%-16s", f_name[i]);
        }
        printf("\n");
        flag = 1;
    }
    // 再打印记录的值
    for(i = 0; i < ncolumn; i++){
        printf("%-16s", f_value[i]);
    }
    printf("\n");
    return 0; // 成功后需要返回0  否则报错 query aborted
}

// 查找所有学员信息的函数--使用回调函数实现
int search_student_1(sqlite3 *my_db){
    // 组装sql语句
    char sqlbuff[256] = {0};
    sprintf(sqlbuff, "SELECT * FROM student");
    // 执行sql语句
    int ret = 0;
    flag = 0; // 重置打印表头的标志位
    if(SQLITE_OK != (ret = sqlite3_exec(my_db, sqlbuff, callback, NULL, NULL))){
        printf("sqlite3_exec error : [%d] [%s]\n", ret, sqlite3_errmsg(my_db));
        exit(EXIT_FAILURE);
    }
    printf("学员信息查询成功..\n");
    return 0;
}

// 查找所有学员信息的函数--使用sqlite3_get_table函数实现
int search_student_2(sqlite3 *my_db){
    // 组装sql语句
    char sqlbuff[256] = {0};
    sprintf(sqlbuff, "SELECT * FROM student");
    char **result = NULL;
    int row = 0;
    int column = 0;
    // 执行sql语句
    int ret = 0;
    if(SQLITE_OK != (ret = sqlite3_get_table(my_db, sqlbuff, &result, &row, &column, NULL))){
        printf("sqlite3_get_table error : [%d] [%s]\n", ret, sqlite3_errmsg(my_db));
        exit(EXIT_FAILURE);
    }
    // 处理查询结果
    // 先打印表头
    int i = 0;
    for(i = 0; i < column; i++){
        printf("%-16s", result[i]);
    }
    printf("\n");
    int index = i;
    // 再打印记录的值
    int j = 0;
    for(i = 0; i < row; i++){
        for(j = 0; j < column; j++){
            // printf("%-16s", result[(i+1)*column+j]);
            printf("%-16s", result[index++]);
        }
        printf("\n");
    }
    printf("学员信息查询成功..\n");
    // 释放结果集
    sqlite3_free_table(result);
    return 0;
}

int main(int argc, const char *argv[]){
    printf("欢迎使用学佳澳学生管理系统..\n");
    // 初始化进程
    sqlite3 *my_db = proc_init();
    
    int choose = 0;
    while(1){
        print_menu();
        scanf("%d", &choose);
        switch(choose){
            case 1:
                insert_student(my_db);
                break;
            case 2:
                modify_student(my_db);
                break;
            case 3:
                delete_student(my_db);
                break;
            case 4:
                //search_student_1(my_db);
                search_student_2(my_db);
                break;
        }
        if(5 == choose)
            break;
    }
    printf("欢迎下次使用..\n");
    // 关闭数据库
    sqlite3_close(my_db);
    return 0;
}
